{
    "cells": [
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "<i>Copyright (c) Recommenders contributors.</i>\n",
                "\n",
                "<i>Licensed under the MIT License.</i>"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "# Wide and Deep Model for Movie Recommendation\n",
                "\n",
                "<br>\n",
                "\n",
                "A linear model with a wide set of crossed-column (co-occurrence) features can memorize the feature interactions, while deep neural networks (DNN) can generalize the feature patterns through low-dimensional dense embeddings learned for the sparse features. [**Wide and Deep**](https://arxiv.org/abs/1606.07792) learning jointly trains wide linear model and deep neural networks to combine the benefits of memorization and generalization for recommender systems.\n",
                "\n",
                "This notebook shows how to build and test the wide-and-deep model using [TensorFlow high-level Estimator API](https://www.tensorflow.org/api_docs/python/tf/estimator/DNNLinearCombinedRegressor). With the [movie recommendation dataset](https://grouplens.org/datasets/movielens/), we quickly demonstrate following topics:\n",
                "1. How to prepare data\n",
                "2. Build the model\n",
                "3. Use log-hook to estimate performance while training\n",
                "4. Test the model and export"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 1,
            "metadata": {},
            "outputs": [],
            "source": [
                "%reload_ext autoreload\n",
                "%autoreload 2\n",
                "%matplotlib inline\n",
                "import warnings\n",
                "warnings.filterwarnings(\"ignore\") "
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 2,
            "metadata": {},
            "outputs": [
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "System version: 3.7.13 (default, Oct 18 2022, 18:57:03) \n",
                        "[GCC 11.2.0]\n",
                        "Tensorflow version: 2.7.4\n",
                        "GPUs: {'device_name': 'Tesla P100-PCIE-16GB', 'total_memory': 16280.875, 'free_memory': 16025.75}\n"
                    ]
                }
            ],
            "source": [
                "import os\n",
                "import sys\n",
                "import math\n",
                "import pandas as pd\n",
                "import sklearn.preprocessing\n",
                "from tempfile import TemporaryDirectory\n",
                "import tensorflow as tf\n",
                "tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.INFO)\n",
                "\n",
                "from recommenders.utils.constants import (\n",
                "    DEFAULT_USER_COL as USER_COL,\n",
                "    DEFAULT_ITEM_COL as ITEM_COL,\n",
                "    DEFAULT_RATING_COL as RATING_COL,\n",
                "    DEFAULT_PREDICTION_COL as PREDICT_COL,\n",
                "    DEFAULT_GENRE_COL as ITEM_FEAT_COL,\n",
                "    SEED\n",
                ")\n",
                "from recommenders.utils import tf_utils, gpu_utils, plot\n",
                "from recommenders.datasets import movielens\n",
                "from recommenders.datasets.pandas_df_utils import user_item_pairs\n",
                "from recommenders.datasets.python_splitters import python_random_split\n",
                "import recommenders.evaluation.python_evaluation as evaluator\n",
                "import recommenders.models.wide_deep.wide_deep_utils as wide_deep\n",
                "from recommenders.utils.notebook_utils import store_metadata\n",
                "\n",
                "print(f\"System version: {sys.version}\")\n",
                "print(f\"Tensorflow version: {tf.__version__}\")\n",
                "print(f\"GPUs: {gpu_utils.get_gpu_info()[0]}\")"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 3,
            "metadata": {
                "tags": [
                    "parameters"
                ]
            },
            "outputs": [],
            "source": [
                "# Parameters \n",
                "\n",
                "# Recommend top k items\n",
                "TOP_K = 10\n",
                "# Select MovieLens data size: 100k, 1m, 10m, or 20m\n",
                "MOVIELENS_DATA_SIZE = \"100k\"\n",
                "# Metrics to use for evaluation\n",
                "RANKING_METRICS = [ evaluator.ndcg_at_k.__name__, evaluator.precision_at_k.__name__ ]\n",
                "RATING_METRICS = [ evaluator.rmse.__name__, evaluator.mae.__name__ ]\n",
                "# Use session hook to evaluate model while training\n",
                "EVALUATE_WHILE_TRAINING = True\n",
                "\n",
                "RANDOM_SEED = SEED  # Set seed for deterministic result\n",
                "\n",
                "# Train and test set pickle file paths. If provided, use them. Otherwise, download the MovieLens dataset.\n",
                "DATA_DIR = None\n",
                "TRAIN_PICKLE_PATH = None\n",
                "TEST_PICKLE_PATH = None\n",
                "EXPORT_DIR_BASE = os.path.join(\"outputs\", \"model\")\n",
                "# Model checkpoints directory. If None, use temp-dir.\n",
                "MODEL_DIR = None\n",
                "\n",
                "#### Hyperparameters\n",
                "MODEL_TYPE = \"wide_deep\"\n",
                "STEPS = 50000  # Number of batches to train\n",
                "BATCH_SIZE = 32\n",
                "# Wide (linear) model hyperparameters\n",
                "LINEAR_OPTIMIZER = \"adagrad\"\n",
                "LINEAR_OPTIMIZER_LR = 0.0621  # Learning rate\n",
                "LINEAR_L1_REG = 0.0           # Regularization rate for FtrlOptimizer\n",
                "LINEAR_L2_REG = 0.0\n",
                "LINEAR_MOMENTUM = 0.0         # Momentum for MomentumOptimizer or RMSPropOptimizer\n",
                "# DNN model hyperparameters\n",
                "DNN_OPTIMIZER = \"adadelta\"\n",
                "DNN_OPTIMIZER_LR = 0.1\n",
                "DNN_L1_REG = 0.0           # Regularization rate for FtrlOptimizer\n",
                "DNN_L2_REG = 0.0\n",
                "DNN_MOMENTUM = 0.0         # Momentum for MomentumOptimizer or RMSPropOptimizer\n",
                "# Layer dimensions. Defined as follows to make this notebook runnable from Hyperparameter tuning services like AzureML Hyperdrive\n",
                "DNN_HIDDEN_LAYER_1 = 0     # Set 0 to not use this layer\n",
                "DNN_HIDDEN_LAYER_2 = 64    # Set 0 to not use this layer\n",
                "DNN_HIDDEN_LAYER_3 = 128   # Set 0 to not use this layer\n",
                "DNN_HIDDEN_LAYER_4 = 512   # Note, at least one layer should have nodes.\n",
                "DNN_HIDDEN_UNITS = [h for h in [DNN_HIDDEN_LAYER_1, DNN_HIDDEN_LAYER_2, DNN_HIDDEN_LAYER_3, DNN_HIDDEN_LAYER_4] if h > 0]\n",
                "DNN_USER_DIM = 32          # User embedding feature dimension\n",
                "DNN_ITEM_DIM = 16          # Item embedding feature dimension\n",
                "DNN_DROPOUT = 0.8\n",
                "DNN_BATCH_NORM = 1         # 1 to use batch normalization, 0 if not."
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 4,
            "metadata": {},
            "outputs": [],
            "source": [
                "if MODEL_DIR is None:\n",
                "    TMP_DIR = TemporaryDirectory()\n",
                "    model_dir = TMP_DIR.name\n",
                "else:\n",
                "    if os.path.exists(MODEL_DIR) and os.listdir(MODEL_DIR):\n",
                "        raise ValueError(\n",
                "            \"Model exists in {}. Use different directory name or \"\n",
                "            \"remove the existing checkpoint files first\".format(MODEL_DIR)\n",
                "        )\n",
                "    TMP_DIR = None\n",
                "    model_dir = MODEL_DIR"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "### 1. Prepare Data\n",
                "\n",
                "#### 1.1 Movie Rating and Genres Data\n",
                "First, download [MovieLens](https://grouplens.org/datasets/movielens/) data. Movies in the data set are tagged as one or more genres where there are total 19 genres including '*unknown*'. We load *movie genres* to use them as item features."
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 5,
            "metadata": {},
            "outputs": [
                {
                    "name": "stderr",
                    "output_type": "stream",
                    "text": [
                        "100%|██████████| 4.81k/4.81k [00:00<00:00, 13.6kKB/s]\n"
                    ]
                },
                {
                    "data": {
                        "text/html": [
                            "<div>\n",
                            "<style scoped>\n",
                            "    .dataframe tbody tr th:only-of-type {\n",
                            "        vertical-align: middle;\n",
                            "    }\n",
                            "\n",
                            "    .dataframe tbody tr th {\n",
                            "        vertical-align: top;\n",
                            "    }\n",
                            "\n",
                            "    .dataframe thead th {\n",
                            "        text-align: right;\n",
                            "    }\n",
                            "</style>\n",
                            "<table border=\"1\" class=\"dataframe\">\n",
                            "  <thead>\n",
                            "    <tr style=\"text-align: right;\">\n",
                            "      <th></th>\n",
                            "      <th>userID</th>\n",
                            "      <th>itemID</th>\n",
                            "      <th>rating</th>\n",
                            "      <th>genre</th>\n",
                            "    </tr>\n",
                            "  </thead>\n",
                            "  <tbody>\n",
                            "    <tr>\n",
                            "      <th>0</th>\n",
                            "      <td>196</td>\n",
                            "      <td>242</td>\n",
                            "      <td>3.0</td>\n",
                            "      <td>Comedy</td>\n",
                            "    </tr>\n",
                            "    <tr>\n",
                            "      <th>1</th>\n",
                            "      <td>63</td>\n",
                            "      <td>242</td>\n",
                            "      <td>3.0</td>\n",
                            "      <td>Comedy</td>\n",
                            "    </tr>\n",
                            "    <tr>\n",
                            "      <th>2</th>\n",
                            "      <td>226</td>\n",
                            "      <td>242</td>\n",
                            "      <td>5.0</td>\n",
                            "      <td>Comedy</td>\n",
                            "    </tr>\n",
                            "    <tr>\n",
                            "      <th>3</th>\n",
                            "      <td>154</td>\n",
                            "      <td>242</td>\n",
                            "      <td>3.0</td>\n",
                            "      <td>Comedy</td>\n",
                            "    </tr>\n",
                            "    <tr>\n",
                            "      <th>4</th>\n",
                            "      <td>306</td>\n",
                            "      <td>242</td>\n",
                            "      <td>5.0</td>\n",
                            "      <td>Comedy</td>\n",
                            "    </tr>\n",
                            "  </tbody>\n",
                            "</table>\n",
                            "</div>"
                        ],
                        "text/plain": [
                            "   userID  itemID  rating   genre\n",
                            "0     196     242     3.0  Comedy\n",
                            "1      63     242     3.0  Comedy\n",
                            "2     226     242     5.0  Comedy\n",
                            "3     154     242     3.0  Comedy\n",
                            "4     306     242     5.0  Comedy"
                        ]
                    },
                    "metadata": {},
                    "output_type": "display_data"
                }
            ],
            "source": [
                "use_preset = (TRAIN_PICKLE_PATH is not None and TEST_PICKLE_PATH is not None)\n",
                "if not use_preset:\n",
                "    # The genres of each movie are returned as '|' separated string, e.g. \"Animation|Children's|Comedy\".\n",
                "    data = movielens.load_pandas_df(\n",
                "        size=MOVIELENS_DATA_SIZE,\n",
                "        header=[USER_COL, ITEM_COL, RATING_COL],\n",
                "        genres_col=ITEM_FEAT_COL\n",
                "    )\n",
                "    display(data.head())"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "#### 1.2 Encode Item Features (Genres)\n",
                "To use genres from our model, we multi-hot-encode them with scikit-learn's [MultiLabelBinarizer](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MultiLabelBinarizer.html).\n",
                "\n",
                "For example, *Movie id=2355* has three genres, *Animation|Children's|Comedy*, which are being converted into an integer array of the indicator value for each genre like `[0, 0, 1, 1, 1, 0, 0, 0, ...]`. In the later step, we convert this into a float array and feed into the model.\n",
                "\n",
                "> For faster feature encoding, you may load ratings and items separately (by using `movielens.load_item_df`), encode the item-features, then combine the rating and item dataframes by using join-operation. "
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 6,
            "metadata": {},
            "outputs": [
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "Genres: ['Action' 'Adventure' 'Animation' \"Children's\" 'Comedy' 'Crime'\n",
                        " 'Documentary' 'Drama' 'Fantasy' 'Film-Noir' 'Horror' 'Musical' 'Mystery'\n",
                        " 'Romance' 'Sci-Fi' 'Thriller' 'War' 'Western' 'unknown']\n"
                    ]
                },
                {
                    "data": {
                        "text/html": [
                            "<div>\n",
                            "<style scoped>\n",
                            "    .dataframe tbody tr th:only-of-type {\n",
                            "        vertical-align: middle;\n",
                            "    }\n",
                            "\n",
                            "    .dataframe tbody tr th {\n",
                            "        vertical-align: top;\n",
                            "    }\n",
                            "\n",
                            "    .dataframe thead th {\n",
                            "        text-align: right;\n",
                            "    }\n",
                            "</style>\n",
                            "<table border=\"1\" class=\"dataframe\">\n",
                            "  <thead>\n",
                            "    <tr style=\"text-align: right;\">\n",
                            "      <th></th>\n",
                            "      <th>userID</th>\n",
                            "      <th>itemID</th>\n",
                            "      <th>rating</th>\n",
                            "      <th>genre</th>\n",
                            "    </tr>\n",
                            "  </thead>\n",
                            "  <tbody>\n",
                            "    <tr>\n",
                            "      <th>0</th>\n",
                            "      <td>196</td>\n",
                            "      <td>242</td>\n",
                            "      <td>3.0</td>\n",
                            "      <td>[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n",
                            "    </tr>\n",
                            "    <tr>\n",
                            "      <th>1</th>\n",
                            "      <td>63</td>\n",
                            "      <td>242</td>\n",
                            "      <td>3.0</td>\n",
                            "      <td>[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n",
                            "    </tr>\n",
                            "    <tr>\n",
                            "      <th>2</th>\n",
                            "      <td>226</td>\n",
                            "      <td>242</td>\n",
                            "      <td>5.0</td>\n",
                            "      <td>[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n",
                            "    </tr>\n",
                            "    <tr>\n",
                            "      <th>3</th>\n",
                            "      <td>154</td>\n",
                            "      <td>242</td>\n",
                            "      <td>3.0</td>\n",
                            "      <td>[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n",
                            "    </tr>\n",
                            "    <tr>\n",
                            "      <th>4</th>\n",
                            "      <td>306</td>\n",
                            "      <td>242</td>\n",
                            "      <td>5.0</td>\n",
                            "      <td>[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...</td>\n",
                            "    </tr>\n",
                            "  </tbody>\n",
                            "</table>\n",
                            "</div>"
                        ],
                        "text/plain": [
                            "   userID  itemID  rating                                              genre\n",
                            "0     196     242     3.0  [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n",
                            "1      63     242     3.0  [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n",
                            "2     226     242     5.0  [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n",
                            "3     154     242     3.0  [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...\n",
                            "4     306     242     5.0  [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ..."
                        ]
                    },
                    "metadata": {},
                    "output_type": "display_data"
                }
            ],
            "source": [
                "if not use_preset and ITEM_FEAT_COL is not None:\n",
                "    # Encode 'genres' into int array (multi-hot representation) to use as item features\n",
                "    genres_encoder = sklearn.preprocessing.MultiLabelBinarizer()\n",
                "    data[ITEM_FEAT_COL] = genres_encoder.fit_transform(\n",
                "        data[ITEM_FEAT_COL].apply(lambda s: s.split(\"|\"))\n",
                "    ).tolist()\n",
                "    print(\"Genres:\", genres_encoder.classes_)\n",
                "    display(data.head())"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "#### 1.3 Train and Test Split"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 7,
            "metadata": {},
            "outputs": [
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "75000 train samples and 25000 test samples\n"
                    ]
                }
            ],
            "source": [
                "if not use_preset:\n",
                "    train, test = python_random_split(data, ratio=0.75, seed=RANDOM_SEED)\n",
                "else:\n",
                "    train = pd.read_pickle(path=TRAIN_PICKLE_PATH if DATA_DIR is None else os.path.join(DATA_DIR, TRAIN_PICKLE_PATH))\n",
                "    test = pd.read_pickle(path=TEST_PICKLE_PATH if DATA_DIR is None else os.path.join(DATA_DIR, TEST_PICKLE_PATH))\n",
                "    data = pd.concat([train, test])\n",
                "\n",
                "print(\"{} train samples and {} test samples\".format(len(train), len(test)))"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 8,
            "metadata": {},
            "outputs": [
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "Total 1682 items and 943 users in the dataset\n"
                    ]
                }
            ],
            "source": [
                "# Unique items in the dataset\n",
                "if ITEM_FEAT_COL is None:\n",
                "    items = data.drop_duplicates(ITEM_COL)[[ITEM_COL]].reset_index(drop=True)\n",
                "    item_feat_shape = None\n",
                "else:\n",
                "    items = data.drop_duplicates(ITEM_COL)[[ITEM_COL, ITEM_FEAT_COL]].reset_index(drop=True)\n",
                "    item_feat_shape = len(items[ITEM_FEAT_COL][0])\n",
                "# Unique users in the dataset\n",
                "users = data.drop_duplicates(USER_COL)[[USER_COL]].reset_index(drop=True)\n",
                "\n",
                "print(\"Total {} items and {} users in the dataset\".format(len(items), len(users)))"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "### 2. Build Model\n",
                "\n",
                "Wide-and-deep model consists of a linear model and DNN. We use the following hyperparameters and feature sets for the model:\n",
                "\n",
                "<br> | <div align=\"center\">Wide (linear) model</div> | <div align=\"center\">Deep neural networks</div>\n",
                "---|---|---\n",
                "Feature set | <ul><li>User-item co-occurrence features<br>to capture how their co-occurrence<br>correlates with the target rating</li></ul> | <ul><li>Deep, lower-dimensional embedding vectors<br>for every user and item</li><li>Item feature vector</li></ul>\n",
                "Hyperparameters | <ul><li>FTRL optimizer</li><li>Learning rate = 0.0029</li><li>L1 regularization = 0.0</li></ul> | <ul><li>Adagrad optimizer</li><li>Learning rate = 0.1</li><li>Hidden units = [128, 256, 32]</li><li>Dropout rate = 0.4</li><li>Use batch normalization (Batch size = 64)</li><li>User embedding vector size = 4</li><li>Item embedding vector size = 4</li></ul>\n",
                "\n",
                "<br>\n",
                "\n",
                "* [FTRL optimizer](https://www.eecs.tufts.edu/~dsculley/papers/ad-click-prediction.pdf)\n",
                "* [Adagrad optimizer](http://www.jmlr.org/papers/volume12/duchi11a/duchi11a.pdf)\n",
                "\n",
                "Note, the hyperparameters are optimized for the training set. We used **Azure Machine Learning service** ([AzureML](https://azure.microsoft.com/en-us/services/machine-learning-service/)) to find the best hyperparameters, where we further split the training set into two subsets for training and validation respectively so that the test set is being separated from the tuning and training phases. For more details, see [azureml_hyperdrive_wide_and_deep.ipynb](../04_model_select_and_optimize/azureml_hyperdrive_wide_and_deep.ipynb)."
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 9,
            "metadata": {},
            "outputs": [],
            "source": [
                "# Create model checkpoint every n steps. We store the model 5 times.\n",
                "save_checkpoints_steps = max(1, STEPS // 5)"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 10,
            "metadata": {},
            "outputs": [
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "Wide feature specs:\n",
                        "\t VocabularyListCategoricalColumn(key='userID', vocabulary_list=(196, 63, 226, 154, 306, 296, 34, 271, ...\n",
                        "\t VocabularyListCategoricalColumn(key='itemID', vocabulary_list=(242, 302, 377, 51, 346, 474, 265, 465 ...\n",
                        "\t CrossedColumn(keys=(VocabularyListCategoricalColumn(key='userID', vocabulary_list=(196, 63, 226, 154 ...\n",
                        "Deep feature specs:\n",
                        "\t EmbeddingColumn(categorical_column=VocabularyListCategoricalColumn(key='userID', vocabulary_list=(19 ...\n",
                        "\t EmbeddingColumn(categorical_column=VocabularyListCategoricalColumn(key='itemID', vocabulary_list=(24 ...\n",
                        "\t NumericColumn(key='genre', shape=(19,), default_value=None, dtype=tf.float32, normalizer_fn=None) ...\n"
                    ]
                }
            ],
            "source": [
                "# Define wide (linear) and deep (dnn) features\n",
                "wide_columns, deep_columns = wide_deep.build_feature_columns(\n",
                "    users=users[USER_COL].values,\n",
                "    items=items[ITEM_COL].values,\n",
                "    user_col=USER_COL,\n",
                "    item_col=ITEM_COL,\n",
                "    item_feat_col=ITEM_FEAT_COL,\n",
                "    crossed_feat_dim=1000,\n",
                "    user_dim=DNN_USER_DIM,\n",
                "    item_dim=DNN_ITEM_DIM,\n",
                "    item_feat_shape=item_feat_shape,\n",
                "    model_type=MODEL_TYPE,\n",
                ")\n",
                "\n",
                "print(\"Wide feature specs:\")\n",
                "for c in wide_columns:\n",
                "    print(\"\\t\", str(c)[:100], \"...\")\n",
                "print(\"Deep feature specs:\")\n",
                "for c in deep_columns:\n",
                "    print(\"\\t\", str(c)[:100], \"...\")"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 11,
            "metadata": {},
            "outputs": [
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpxxoy5_91', '_tf_random_seed': 42, '_save_summary_steps': 100, '_save_checkpoints_steps': 10000, '_save_checkpoints_secs': None, '_session_config': gpu_options {\n",
                        "  allow_growth: true\n",
                        "}\n",
                        ", '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 5000, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_checkpoint_save_graph_def': True, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}\n"
                    ]
                }
            ],
            "source": [
                "# Build a model based on the parameters\n",
                "model = wide_deep.build_model(\n",
                "    model_dir=model_dir,\n",
                "    wide_columns=wide_columns,\n",
                "    deep_columns=deep_columns,\n",
                "    linear_optimizer=tf_utils.build_optimizer(LINEAR_OPTIMIZER, LINEAR_OPTIMIZER_LR, **{\n",
                "        'l1_regularization_strength': LINEAR_L1_REG,\n",
                "        'l2_regularization_strength': LINEAR_L2_REG,\n",
                "        'momentum': LINEAR_MOMENTUM,\n",
                "    }),\n",
                "    dnn_optimizer=tf_utils.build_optimizer(DNN_OPTIMIZER, DNN_OPTIMIZER_LR, **{\n",
                "        'l1_regularization_strength': DNN_L1_REG,\n",
                "        'l2_regularization_strength': DNN_L2_REG,\n",
                "        'momentum': DNN_MOMENTUM,  \n",
                "    }),\n",
                "    dnn_hidden_units=DNN_HIDDEN_UNITS,\n",
                "    dnn_dropout=DNN_DROPOUT,\n",
                "    dnn_batch_norm=(DNN_BATCH_NORM==1),\n",
                "    log_every_n_iter=max(1, STEPS//10),  # log 10 times\n",
                "    save_checkpoints_steps=save_checkpoints_steps,\n",
                "    seed=RANDOM_SEED\n",
                ")"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "### 3. Train and Evaluate Model\n",
                "\n",
                "Now we are all set to train the model. Here, we show how to utilize session hooks to track model performance while training. Our custom hook `tf_utils.evaluation_log_hook` estimates the model performance on the given data based on the specified evaluation functions. Note we pass test set to evaluate the model on rating metrics while we use <span id=\"ranking-pool\">ranking-pool (all the user-item pairs)</span> for ranking metrics.\n",
                "\n",
                "> Note: The TensorFlow Estimator's default loss calculates Mean Squared Error. Square root of the loss is the same as [RMSE](https://en.wikipedia.org/wiki/Root-mean-square_deviation)."
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 12,
            "metadata": {},
            "outputs": [],
            "source": [
                "cols = {\n",
                "    'col_user': USER_COL,\n",
                "    'col_item': ITEM_COL,\n",
                "    'col_rating': RATING_COL,\n",
                "    'col_prediction': PREDICT_COL,\n",
                "}\n",
                "\n",
                "# Prepare ranking evaluation set, i.e. get the cross join of all user-item pairs\n",
                "ranking_pool = user_item_pairs(\n",
                "    user_df=users,\n",
                "    item_df=items,\n",
                "    user_col=USER_COL,\n",
                "    item_col=ITEM_COL,\n",
                "    user_item_filter_df=train,  # Remove seen items\n",
                "    shuffle=True,\n",
                "    seed=RANDOM_SEED\n",
                ")"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 13,
            "metadata": {},
            "outputs": [],
            "source": [
                "# Define training hooks to track performance while training\n",
                "hooks = []\n",
                "if EVALUATE_WHILE_TRAINING:\n",
                "    evaluation_logger = tf_utils.MetricsLogger()\n",
                "    for metrics in (RANKING_METRICS, RATING_METRICS):\n",
                "        if len(metrics) > 0:\n",
                "            hooks.append(\n",
                "                tf_utils.evaluation_log_hook(\n",
                "                    model,\n",
                "                    logger=evaluation_logger,\n",
                "                    true_df=test,\n",
                "                    y_col=RATING_COL,\n",
                "                    eval_df=ranking_pool if metrics==RANKING_METRICS else test.drop(RATING_COL, axis=1),\n",
                "                    every_n_iter=save_checkpoints_steps,\n",
                "                    model_dir=model_dir,\n",
                "                    eval_fns=[evaluator.metrics[m] for m in metrics],\n",
                "                    **({**cols, 'k': TOP_K} if metrics==RANKING_METRICS else cols)\n",
                "                )\n",
                "            )\n",
                "\n",
                "# Define training input (sample feeding) function\n",
                "train_fn = tf_utils.pandas_input_fn(\n",
                "    df=train,\n",
                "    y_col=RATING_COL,\n",
                "    batch_size=BATCH_SIZE,\n",
                "    num_epochs=None,  # We use steps=TRAIN_STEPS instead.\n",
                "    shuffle=True,\n",
                "    seed=RANDOM_SEED,\n",
                ")"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "Let's train the model."
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 14,
            "metadata": {},
            "outputs": [
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "Training steps = 50000, Batch size = 32 (num epochs = 21)\n",
                        "WARNING:tensorflow:From /anaconda/envs/reco_gpu/lib/python3.7/site-packages/tensorflow/python/training/training_util.py:401: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version.\n",
                        "Instructions for updating:\n",
                        "Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts.\n",
                        "INFO:tensorflow:Calling model_fn.\n",
                        "WARNING:tensorflow:From /anaconda/envs/reco_gpu/lib/python3.7/site-packages/keras/layers/normalization/batch_normalization.py:532: _colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
                        "Instructions for updating:\n",
                        "Colocations handled automatically by placer.\n",
                        "WARNING:tensorflow:From /anaconda/envs/reco_gpu/lib/python3.7/site-packages/tensorflow/python/training/adagrad.py:143: calling Constant.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.\n",
                        "Instructions for updating:\n",
                        "Call initializer instance with the dtype argument instead of passing it to the constructor\n",
                        "INFO:tensorflow:Done calling model_fn.\n",
                        "INFO:tensorflow:Create CheckpointSaverHook.\n",
                        "INFO:tensorflow:Graph was finalized.\n"
                    ]
                },
                {
                    "name": "stderr",
                    "output_type": "stream",
                    "text": [
                        "2022-11-17 10:10:24.088929: I tensorflow/core/platform/cpu_feature_guard.cc:151] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 FMA\n",
                        "To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n"
                    ]
                },
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "INFO:tensorflow:Running local_init_op.\n"
                    ]
                },
                {
                    "name": "stderr",
                    "output_type": "stream",
                    "text": [
                        "2022-11-17 10:10:24.531719: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n"
                    ]
                },
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "INFO:tensorflow:Done running local_init_op.\n",
                        "INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0...\n",
                        "INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpxxoy5_91/model.ckpt.\n",
                        "INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0...\n"
                    ]
                },
                {
                    "name": "stderr",
                    "output_type": "stream",
                    "text": [
                        "2022-11-17 10:10:30.553224: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n",
                        "2022-11-17 10:11:14.781044: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n"
                    ]
                },
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "INFO:tensorflow:loss = 432.81842, step = 0\n",
                        "INFO:tensorflow:global_step/sec: 51.8858\n",
                        "INFO:tensorflow:loss = 37.710823, step = 5000 (48.264 sec)\n",
                        "INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 10000...\n",
                        "INFO:tensorflow:Saving checkpoints for 10000 into /tmp/tmpxxoy5_91/model.ckpt.\n",
                        "INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 10000...\n",
                        "INFO:tensorflow:global_step/sec: 104.604\n"
                    ]
                },
                {
                    "name": "stderr",
                    "output_type": "stream",
                    "text": [
                        "2022-11-17 10:12:54.706062: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n",
                        "2022-11-17 10:13:39.157050: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n"
                    ]
                },
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "INFO:tensorflow:loss = 18.64918, step = 10000 (96.084 sec)\n",
                        "INFO:tensorflow:global_step/sec: 51.957\n",
                        "INFO:tensorflow:loss = 19.740814, step = 15000 (47.948 sec)\n",
                        "INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 20000...\n",
                        "INFO:tensorflow:Saving checkpoints for 20000 into /tmp/tmpxxoy5_91/model.ckpt.\n",
                        "INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 20000...\n",
                        "INFO:tensorflow:global_step/sec: 104.198\n"
                    ]
                },
                {
                    "name": "stderr",
                    "output_type": "stream",
                    "text": [
                        "2022-11-17 10:15:18.899211: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n",
                        "2022-11-17 10:16:03.296840: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n"
                    ]
                },
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "INFO:tensorflow:loss = 37.00244, step = 20000 (96.187 sec)\n",
                        "INFO:tensorflow:global_step/sec: 52.0448\n",
                        "INFO:tensorflow:loss = 27.582132, step = 25000 (47.869 sec)\n",
                        "INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 30000...\n",
                        "INFO:tensorflow:Saving checkpoints for 30000 into /tmp/tmpxxoy5_91/model.ckpt.\n",
                        "INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 30000...\n",
                        "INFO:tensorflow:global_step/sec: 104.012\n"
                    ]
                },
                {
                    "name": "stderr",
                    "output_type": "stream",
                    "text": [
                        "2022-11-17 10:17:43.070172: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n",
                        "2022-11-17 10:18:26.803461: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n"
                    ]
                },
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "INFO:tensorflow:loss = 28.610579, step = 30000 (95.663 sec)\n",
                        "INFO:tensorflow:global_step/sec: 52.4622\n",
                        "INFO:tensorflow:loss = 28.54421, step = 35000 (47.715 sec)\n",
                        "INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 40000...\n",
                        "INFO:tensorflow:Saving checkpoints for 40000 into /tmp/tmpxxoy5_91/model.ckpt.\n",
                        "INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 40000...\n",
                        "INFO:tensorflow:global_step/sec: 104.755\n"
                    ]
                },
                {
                    "name": "stderr",
                    "output_type": "stream",
                    "text": [
                        "2022-11-17 10:20:06.106187: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n",
                        "2022-11-17 10:20:50.170488: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n"
                    ]
                },
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "INFO:tensorflow:loss = 25.694395, step = 40000 (95.642 sec)\n",
                        "INFO:tensorflow:global_step/sec: 52.3988\n",
                        "INFO:tensorflow:loss = 21.772835, step = 45000 (47.511 sec)\n",
                        "INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 50000...\n",
                        "INFO:tensorflow:Saving checkpoints for 50000 into /tmp/tmpxxoy5_91/model.ckpt.\n",
                        "WARNING:tensorflow:From /anaconda/envs/reco_gpu/lib/python3.7/site-packages/tensorflow/python/training/saver.py:1058: remove_checkpoint (from tensorflow.python.training.checkpoint_management) is deprecated and will be removed in a future version.\n",
                        "Instructions for updating:\n",
                        "Use standard file APIs to delete files with this prefix.\n",
                        "INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 50000...\n",
                        "INFO:tensorflow:Loss for final step: 23.8424.\n",
                        "CPU times: user 23min 44s, sys: 8min 26s, total: 32min 10s\n",
                        "Wall time: 12min 4s\n"
                    ]
                }
            ],
            "source": [
                "%%time\n",
                "print(\n",
                "    \"Training steps = {}, Batch size = {} (num epochs = {})\"\n",
                "    .format(STEPS, BATCH_SIZE, (STEPS*BATCH_SIZE)//len(train))\n",
                ")\n",
                "\n",
                "try:\n",
                "    model.train(\n",
                "        input_fn=train_fn,\n",
                "        hooks=hooks,\n",
                "        steps=STEPS\n",
                "    )\n",
                "except tf.train.NanLossDuringTrainingError:\n",
                "    import warnings\n",
                "    warnings.warn(\n",
                "        \"Training stopped with NanLossDuringTrainingError. \"\n",
                "        \"Try other optimizers, smaller batch size and/or smaller learning rate.\"\n",
                "    )"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 15,
            "metadata": {
                "tags": []
            },
            "outputs": [
                {
                    "data": {
                        "application/scrapbook.scrap.json+json": {
                            "data": [
                                0.014169790473514552,
                                0.13641404033571355,
                                0.11442188208986268,
                                0.10049193571741831,
                                0.09128434529185275
                            ],
                            "encoder": "json",
                            "name": "eval_ndcg_at_k",
                            "version": 1
                        }
                    },
                    "metadata": {
                        "scrapbook": {
                            "data": true,
                            "display": false,
                            "name": "eval_ndcg_at_k"
                        }
                    },
                    "output_type": "display_data"
                },
                {
                    "data": {
                        "application/scrapbook.scrap.json+json": {
                            "data": [
                                0.013467656415694591,
                                0.12704135737009548,
                                0.10858960763520681,
                                0.09766702014846236,
                                0.0909862142099682
                            ],
                            "encoder": "json",
                            "name": "eval_precision_at_k",
                            "version": 1
                        }
                    },
                    "metadata": {
                        "scrapbook": {
                            "data": true,
                            "display": false,
                            "name": "eval_precision_at_k"
                        }
                    },
                    "output_type": "display_data"
                },
                {
                    "data": {
                        "application/scrapbook.scrap.json+json": {
                            "data": [
                                3.7706172276562215,
                                0.9701889338613858,
                                0.9577112599486723,
                                0.9542696275522176,
                                0.9528089498633402
                            ],
                            "encoder": "json",
                            "name": "eval_rmse",
                            "version": 1
                        }
                    },
                    "metadata": {
                        "scrapbook": {
                            "data": true,
                            "display": false,
                            "name": "eval_rmse"
                        }
                    },
                    "output_type": "display_data"
                },
                {
                    "data": {
                        "application/scrapbook.scrap.json+json": {
                            "data": [
                                3.5965963473848395,
                                0.779636345512867,
                                0.7643329776144028,
                                0.7599420306742192,
                                0.7578409026277065
                            ],
                            "encoder": "json",
                            "name": "eval_mae",
                            "version": 1
                        }
                    },
                    "metadata": {
                        "scrapbook": {
                            "data": true,
                            "display": false,
                            "name": "eval_mae"
                        }
                    },
                    "output_type": "display_data"
                },
                {
                    "data": {
                        "image/png": "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b0BSLSkpkdPp1LRp0/xjzve54+PjNXv27IAxPp9Pb775pmX35lw+n09tbW1RfU/mz5+vvXv3qqKiwr9cddVVWrZsmf/P0XpvztXc3Kw//elPysrKiup/ZjD6kUPJoYNBDiWHBiPic2hQr+IYhZqamszy8nKzvLzclGT+53/+p1leXm4eOXLENM3uV+G6XC7zlVdeMffs2WMuXry431fh5uXlme+995759ttvm5dffnnAq3Dr6+vNjIwM87bbbjP37dtnrl271kxKSurzKtzY2FjzP/7jP8wPPvjAfPDBBy19Fe7f/d3fmampqWZpaWnAKzxPnTrlH3P33XebHo/H3LJli7lr1y4zPz/fzM/P9+/veYXnDTfcYFZUVJibNm0yx40b1+8rPO+//37zgw8+MB9//PF+X+HpcDjM4uJi88CBA+b//t//23S5XAFvqBkp//iP/2hu27bNrKysNPfs2WP+4z/+o2mz2czNmzebphmd92Qgvd/IZJrRe2/uu+8+s7S01KysrDTfeecdc8GCBebYsWPNEydOmKYZvfcFowM5tH/k0P6RQwePHNpttOXQqC+8tm7dakrqs9x+++2maXa/Dvf//t//a2ZkZJgOh8OcP3++efDgwYBzfP755+bSpUvN5ORk0+l0mnfccYfZ1NQUMOb99983/+zP/sx0OBzm+PHjzYceeqhPLC+++KJ5xRVXmPHx8eb06dPN1157LWSf+0L6uyeSzN/+9rf+MadPnzb/z//5P6bb7TaTkpLMv/zLvzRramoCzvPJJ5+YixYtMhMTE82xY8ea9913n9nR0REwZuvWreaVV15pxsfHm5dddlnANXo8+uijpsfjMePj481rrrnG3LlzZyg+9gX97d/+ren1es34+Hhz3Lhx5vz58/0JwzSj854M5NykEa335lvf+paZlZVlxsfHm+PHjze/9a1vmYcOHfLvj9b7gtGBHNo/cmj/yKGDRw7tNtpyqM00TTO438gAAAAAAMFgjhcAAAAAhBiFFwAAAACEGIUXAAAAAIQYhRcAAAAAhBiFFwAAAACEGIUXAAAAAIQYhRcAAAAAhBiFFwAAAACEGIUXEALf+c53tGTJEqvDAAAg4pBDMVpReAEAAABAiFF4ARdh3bp1mjlzphITE3XJJZdowYIFuv/++/X//t//0yuvvCKbzSabzabS0lJJUnV1tb75zW/K5XIpLS1Nixcv1ieffOI/X8+3fD/72c80btw4OZ1O3X333Wpvbz/vNVtaWkb4kwMAcHHIoYg2sVYHAESqmpoaLV26VL/4xS/0l3/5l2pqatJbb72l5cuXq6qqSo2Njfrtb38rSUpLS1NHR4cWLlyo/Px8vfXWW4qNjdW//Mu/6MYbb9SePXsUHx8vSXrzzTeVkJCg0tJSffLJJ7rjjjt0ySWX6F//9V8HvKZpmlbeCgAAgkIORVQyAQzJ7t27TUnmJ5980mff7bffbi5evDhg23//93+bkydPNn0+n39bW1ubmZiYaL7xxhv+49LS0syWlhb/mDVr1pjJyclmV1fXea8JAECkIIciGvGoITBEubm5mj9/vmbOnKlbb71Vv/nNb3Ty5MkBx7///vs6dOiQUlJSlJycrOTkZKWlpam1tVV/+tOfAs6blJTkX8/Pz1dzc7Oqq6uDviYAAOGIHIpoROEFDFFMTIxKSkr0+uuva9q0aXr00Uc1efJkVVZW9ju+ublZs2fPVkVFRcDy0Ucf6W/+5m9Cck0AAMIRORTRiMILuAg2m01z587Vz372M5WXlys+Pl7r169XfHy8urq6AsYahqGPP/5Y6enpmjRpUsCSmprqH/f+++/r9OnT/vWdO3cqOTlZOTk5570mAACRhByKaEPhBQzRe++9p3/7t3/Trl27VFVVpZdfflmffvqppk6dqksvvVR79uzRwYMH9dlnn6mjo0PLli3T2LFjtXjxYr311luqrKxUaWmpvv/97+vo0aP+87a3t+vOO+/UgQMHtHHjRj344INasWKF7Hb7ea8JAECkIIciGvFWQ2CInE6ntm/frocffliNjY3yer1atWqVFi1apKuuukqlpaW66qqr1NzcrK1bt2revHnavn27fvjDH+rrX/+6mpqaNH78eM2fP19Op9N/3vnz5+vyyy/Xddddp7a2Ni1dulQ//elPL3hNAAAiBTkU0chmmrxDEwgX3/nOd1RfX68NGzZYHQoAABGFHIpwx6OGAAAAABBiFF4AAAAAEGI8aggAAAAAIcYvXgAAAAAQYhReAAAAABBiFF4AAAAAEGIUXgAAAAAQYhReAAAAABBiFF4AAAAAEGIUXgAAAAAQYhReAAAAABBiFF4AAAAAEGL/H6tugObc1Ge8AAAAAElFTkSuQmCC",
                        "text/plain": [
                            "<Figure size 1000x1000 with 4 Axes>"
                        ]
                    },
                    "metadata": {},
                    "output_type": "display_data"
                }
            ],
            "source": [
                "if EVALUATE_WHILE_TRAINING:\n",
                "    logs = evaluation_logger.get_log()\n",
                "    for i, (m, v) in enumerate(logs.items(), 1):\n",
                "        store_metadata(\"eval_{}\".format(m), v)\n",
                "        x = [save_checkpoints_steps*i for i in range(1, len(v)+1)]\n",
                "        plot.line_graph(\n",
                "            values=list(zip(v, x)),\n",
                "            labels=m,\n",
                "            x_name=\"steps\",\n",
                "            y_name=m,\n",
                "            subplot=(math.ceil(len(logs)/2), 2, i),\n",
                "        )"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "#### 3.2 TensorBoard\n",
                "\n",
                "Once the train is done, you can browse the details of the training results as well as the metrics we logged from [TensorBoard](https://www.tensorflow.org/guide/summaries_and_tensorboard).\n",
                "\n",
                "[]()|[]()|[]()\n",
                ":---:|:---:|:---:\n",
                "<img src=\"https://recodatasets.z20.web.core.windows.net/images/tensorboard_0.png?sanitize=true\"> |  <img src=\"https://recodatasets.z20.web.core.windows.net/images/tensorboard_1.png?sanitize=true\"> | <img src=\"https://recodatasets.z20.web.core.windows.net/images/tensorboard_2.png?sanitize=true\">\n",
                "\n",
                "To open the TensorBoard, open a terminal from the same directory of this notebook, run `tensorboard --logdir=model_checkpoints`, and open http://localhost:6006 from a browser.\n",
                "\n"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "### 4. Test and Export Model\n",
                "\n",
                "#### 4.1 Item rating prediction"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 16,
            "metadata": {},
            "outputs": [
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "INFO:tensorflow:Calling model_fn.\n",
                        "INFO:tensorflow:Done calling model_fn.\n",
                        "INFO:tensorflow:Graph was finalized.\n",
                        "INFO:tensorflow:Restoring parameters from /tmp/tmpxxoy5_91/model.ckpt-50000\n",
                        "INFO:tensorflow:Running local_init_op.\n",
                        "INFO:tensorflow:Done running local_init_op.\n"
                    ]
                },
                {
                    "name": "stderr",
                    "output_type": "stream",
                    "text": [
                        "2022-11-17 10:22:27.706090: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n"
                    ]
                },
                {
                    "data": {
                        "application/scrapbook.scrap.json+json": {
                            "data": 0.9526174435076816,
                            "encoder": "json",
                            "name": "rmse",
                            "version": 1
                        }
                    },
                    "metadata": {
                        "scrapbook": {
                            "data": true,
                            "display": false,
                            "name": "rmse"
                        }
                    },
                    "output_type": "display_data"
                },
                {
                    "data": {
                        "application/scrapbook.scrap.json+json": {
                            "data": 0.7576649205052852,
                            "encoder": "json",
                            "name": "mae",
                            "version": 1
                        }
                    },
                    "metadata": {
                        "scrapbook": {
                            "data": true,
                            "display": false,
                            "name": "mae"
                        }
                    },
                    "output_type": "display_data"
                },
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "{'rmse': 0.9526174435076816, 'mae': 0.7576649205052852}\n"
                    ]
                }
            ],
            "source": [
                "if len(RATING_METRICS) > 0:\n",
                "    predictions = list(model.predict(input_fn=tf_utils.pandas_input_fn(df=test)))\n",
                "    prediction_df = test.drop(RATING_COL, axis=1)\n",
                "    prediction_df[PREDICT_COL] = [p['predictions'][0] for p in predictions]\n",
                "    \n",
                "    rating_results = {}\n",
                "    for m in RATING_METRICS:\n",
                "        result = evaluator.metrics[m](test, prediction_df, **cols)\n",
                "        store_metadata(m, result)\n",
                "        rating_results[m] = result\n",
                "    print(rating_results)"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "#### 4.2 Recommend k items\n",
                "For top-k recommendation evaluation, we use the ranking pool (all the user-item pairs) we prepared at the [training step](#ranking-pool). The difference is we remove users' seen items from the pool in this step which is more natural to the movie recommendation scenario."
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 17,
            "metadata": {},
            "outputs": [
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "INFO:tensorflow:Calling model_fn.\n",
                        "INFO:tensorflow:Done calling model_fn.\n",
                        "INFO:tensorflow:Graph was finalized.\n",
                        "INFO:tensorflow:Restoring parameters from /tmp/tmpxxoy5_91/model.ckpt-50000\n",
                        "INFO:tensorflow:Running local_init_op.\n",
                        "INFO:tensorflow:Done running local_init_op.\n"
                    ]
                },
                {
                    "name": "stderr",
                    "output_type": "stream",
                    "text": [
                        "2022-11-17 10:22:32.539473: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n"
                    ]
                },
                {
                    "data": {
                        "application/scrapbook.scrap.json+json": {
                            "data": 0.08594396229187452,
                            "encoder": "json",
                            "name": "ndcg_at_k",
                            "version": 1
                        }
                    },
                    "metadata": {
                        "scrapbook": {
                            "data": true,
                            "display": false,
                            "name": "ndcg_at_k"
                        }
                    },
                    "output_type": "display_data"
                },
                {
                    "data": {
                        "application/scrapbook.scrap.json+json": {
                            "data": 0.08557794273594911,
                            "encoder": "json",
                            "name": "precision_at_k",
                            "version": 1
                        }
                    },
                    "metadata": {
                        "scrapbook": {
                            "data": true,
                            "display": false,
                            "name": "precision_at_k"
                        }
                    },
                    "output_type": "display_data"
                },
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "{'ndcg_at_k': 0.08594396229187452, 'precision_at_k': 0.08557794273594911}\n"
                    ]
                }
            ],
            "source": [
                "if len(RANKING_METRICS) > 0:\n",
                "    predictions = list(model.predict(input_fn=tf_utils.pandas_input_fn(df=ranking_pool)))\n",
                "    prediction_df = ranking_pool.copy()\n",
                "    prediction_df[PREDICT_COL] = [p['predictions'][0] for p in predictions]\n",
                "\n",
                "    ranking_results = {}\n",
                "    for m in RANKING_METRICS:\n",
                "        result = evaluator.metrics[m](test, prediction_df, **{**cols, 'k': TOP_K})\n",
                "        store_metadata(m, result)\n",
                "        ranking_results[m] = result\n",
                "    print(ranking_results)"
            ]
        },
        {
            "cell_type": "markdown",
            "metadata": {},
            "source": [
                "#### 4.3 Export Model\n",
                "Finally, we export the model so that we can load later for re-training, evaluation, and prediction.\n",
                "Examples of how to load, re-train, and evaluate the saved model can be found from [azureml_hyperdrive_wide_and_deep.ipynb](../04_model_select_and_optimize/azureml_hyperdrive_wide_and_deep.ipynb) notebook."
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 18,
            "metadata": {},
            "outputs": [],
            "source": [
                "os.makedirs(EXPORT_DIR_BASE, exist_ok=True)"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 19,
            "metadata": {
                "scrolled": true
            },
            "outputs": [
                {
                    "name": "stderr",
                    "output_type": "stream",
                    "text": [
                        "2022-11-17 10:23:50.290357: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n",
                        "2022-11-17 10:23:51.393927: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n",
                        "2022-11-17 10:23:52.162989: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1525] Created device /job:localhost/replica:0/task:0/device:GPU:0 with 15397 MB memory:  -> device: 0, name: Tesla P100-PCIE-16GB, pci bus id: 0001:00:00.0, compute capability: 6.0\n"
                    ]
                },
                {
                    "data": {
                        "application/scrapbook.scrap.text+json": {
                            "data": "outputs/model/1668680629",
                            "encoder": "text",
                            "name": "saved_model_dir",
                            "version": 1
                        }
                    },
                    "metadata": {
                        "scrapbook": {
                            "data": true,
                            "display": false,
                            "name": "saved_model_dir"
                        }
                    },
                    "output_type": "display_data"
                },
                {
                    "name": "stdout",
                    "output_type": "stream",
                    "text": [
                        "Model exported to outputs/model/1668680629\n"
                    ]
                }
            ],
            "source": [
                "exported_path = tf_utils.export_model(\n",
                "    model=model,\n",
                "    train_input_fn=train_fn,\n",
                "    eval_input_fn=tf_utils.pandas_input_fn(\n",
                "        df=test, y_col=RATING_COL\n",
                "    ),\n",
                "    tf_feat_cols=wide_columns+deep_columns,\n",
                "    base_dir=EXPORT_DIR_BASE\n",
                ")\n",
                "store_metadata('saved_model_dir', str(exported_path))\n",
                "print(\"Model exported to\", str(exported_path))"
            ]
        },
        {
            "cell_type": "code",
            "execution_count": 20,
            "metadata": {},
            "outputs": [],
            "source": [
                "# Close the event file so that the model folder can be cleaned up.\n",
                "summary_writer = tf.compat.v1.summary.FileWriterCache.get(model.model_dir)\n",
                "summary_writer.close()\n",
                "\n",
                "# Cleanup temporary directory if used\n",
                "if TMP_DIR is not None:\n",
                "    TMP_DIR.cleanup()"
            ]
        }
    ],
    "metadata": {
        "interpreter": {
            "hash": "3a9a0c422ff9f08d62211b9648017c63b0a26d2c935edc37ebb8453675d13bb5"
        },
        "kernelspec": {
            "display_name": "reco_gpu",
            "language": "python",
            "name": "conda-env-reco_gpu-py"
        },
        "language_info": {
            "codemirror_mode": {
                "name": "ipython",
                "version": 3
            },
            "file_extension": ".py",
            "mimetype": "text/x-python",
            "name": "python",
            "nbconvert_exporter": "python",
            "pygments_lexer": "ipython3",
            "version": "3.7.13"
        }
    },
    "nbformat": 4,
    "nbformat_minor": 4
}
